﻿using System;
using System.Linq;
using System.Threading.Tasks;
using DotNetCore.CAP;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Business.LCZX;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.RecurringJobs.Dto;
using Serilog;
using SqlSugar;

namespace NP.BPMReportPlatform.RecurringJobs
{
    public class LBDXRecurringJob : BpmReportPlatformRecurringJob, ILBDXRecurringJob
    {
        private readonly SqlSugarClient _db, _dbPlatform;
        private ICapPublisher _capBus;
        private readonly ILogger _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sqlSugarAppService"></param>
        public LBDXRecurringJob(ISqlSugarAppService sqlSugarAppService, ICapPublisher publisher, ILogger logger)
        {
            _capBus = publisher;
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _logger = logger;
        }

        /// <summary>
        /// 同步课程数据到CourseBase表
        /// </summary>
        /// <param name="materialCode"></param>
        public async Task SyncDataToCourseBase()
        {
            try
            {
                var details = await _db.Queryable<LBDXListingApplicationDetail>().ToListAsync();
                var instaceNumbers = details.Select(q => q.InstanceNumber);
                var materialCodes = details.Select(x => x.MaterialCode);
                var headers = await _db.Queryable<LBDXListingApplicationHeader>().Where(x => instaceNumbers.Contains(x.InstanceNumber)).ToListAsync();
                var detailChildrens = await _db.Queryable<LBDXListingApplicationDetailChild>().Where(x => instaceNumbers.Contains(x.InstanceNumber)).ToListAsync();
                var gjHeaders = await _db.Queryable<LCZXCPGJHeader, BusinessProcessesNew>((x, b) => x.InstanceNumber == b.InstanceId)
                            .Where((x, b) => materialCodes.Contains(x.MaterialCode) && b.ProcessStatusCode == "approved" &&
                            x.ValidStartTime <= DateTime.Now && x.ValidEndTime >= DateTime.Now)
                            .OrderBy(x => x.ValidEndTime, OrderByType.Desc).ToListAsync();
                var courseBases = await _db.Queryable<CourseBase>().Where(x => x.Status == 1).ToListAsync();
                var businessProcesses = await _db.Queryable<BusinessProcessesNew>().Where(x => instaceNumbers.Contains(x.InstanceId) && x.ProcessStatusCode == "approved").ToListAsync();
                foreach (var detail in details)
                {
                    var instanceNumber = detail.InstanceNumber;
                    var materialCode = detail.MaterialCode;

                    var courseBase = courseBases.FirstOrDefault(x => x.CourseCode == materialCode);

                    var header = headers.FirstOrDefault(x => x.InstanceNumber == instanceNumber);
                    var detailChildren = detailChildrens.Where(x => x.InstanceNumber == instanceNumber).ToList();
                    if (header == null || !details.Any() || !detailChildren.Any())
                    {
                        continue;
                    }

                    var businessProcess = businessProcesses.FirstOrDefault(x => x.InstanceId == instanceNumber);
                    if (businessProcess == null)
                    {
                        continue;
                    }

                    var gjHeader = gjHeaders.FirstOrDefault(x => x.MaterialCode == materialCode);
                    if (gjHeader == null)
                    {
                        var children = detailChildren
                            .Where(x => x.StartDate <= DateTime.Now && x.EndDate >= DateTime.Now && SqlFunc.ToString(x.LBDXListingApplicationDetailId) == detail.Id)
                            .OrderByDescending(x => x.EndDate).FirstOrDefault();
                        if (children == null)
                        {
                            continue;
                        }

                        if (courseBase == null)
                        {
                            var entity = new CourseBase
                            {
                                Id = Guid.NewGuid(),
                                CourseCode = detail.MaterialCode,
                                CourseName = detail.ProductName,
                                Amount = children.Amount,
                                CourseNature = detail.CourseNature,
                                TeachWayCode = detail.TeachWayName,
                                ChargeTypeCode = detail.ChargeTypeName,
                                TrainingObjects = detail.TrainObject,
                                BU = header.DemandSourceName,
                                EstimatedNumberClasses = header.EstimatedNumberClasses,
                                ChargeDif = detail.PricingUnit,
                                TrainDays = detail.Days,
                                StandardTeacherCount = detail.StandardTeacherCount,
                                StandardStudentCount = detail.StandardStudentCount,
                                CreateUserId = businessProcess.StartUserId,
                                CreateDate = businessProcess.FinishTime,
                                Status = 1,
                            };

                            await _db.Insertable(entity).ExecuteCommandAsync();
                        }
                        else
                        {
                            courseBase.CourseName = detail.ProductName;
                            courseBase.Amount = children.Amount;
                            if (!string.IsNullOrWhiteSpace(detail.CourseNature))
                            {
                                courseBase.CourseNature = detail.CourseNature;
                            }
                            courseBase.TeachWayCode = detail.TeachWayName;
                            courseBase.ChargeTypeCode = detail.ChargeTypeName;
                            if (!string.IsNullOrWhiteSpace(detail.TrainObject))
                            {
                                courseBase.TrainingObjects = detail.TrainObject;
                            }
                            courseBase.BU = header.DemandSourceName;
                            courseBase.EstimatedNumberClasses = header.EstimatedNumberClasses;
                            courseBase.ChargeDif = detail.PricingUnit;
                            courseBase.TrainDays = detail.Days;
                            courseBase.StandardTeacherCount = detail.StandardTeacherCount;
                            courseBase.StandardStudentCount = detail.StandardStudentCount;
                            courseBase.CreateUserId = businessProcess.StartUserId;
                            courseBase.CreateDate = businessProcess.FinishTime;
                            courseBase.Status = 1;

                            await _db.Updateable(courseBase).ExecuteCommandAsync();
                        }
                    }
                    else if (gjHeader != null && gjHeader.Price.HasValue && gjHeader.ClassCount.HasValue &&
                        !string.IsNullOrEmpty(gjHeader.Unit) && gjHeader.PeopleCount.HasValue)
                    {
                        if (courseBase == null)
                        {
                            var entity = new CourseBase
                            {
                                Id = Guid.NewGuid(),
                                CourseCode = detail.MaterialCode,
                                CourseName = detail.ProductName,
                                Amount = gjHeader.Price.Value,
                                CourseNature = detail.CourseNature,
                                TeachWayCode = detail.TeachWayName,
                                ChargeTypeCode = detail.ChargeTypeName,
                                TrainingObjects = detail.TrainObject,
                                BU = header.DemandSourceName,
                                EstimatedNumberClasses = gjHeader.ClassCount.Value,
                                ChargeDif = gjHeader.Unit,
                                TrainDays = detail.Days,
                                StandardTeacherCount = detail.StandardTeacherCount,
                                StandardStudentCount = gjHeader.PeopleCount.Value,
                                CreateUserId = businessProcess.StartUserId,
                                CreateDate = businessProcess.FinishTime,
                                Status = 1,
                            };

                            await _db.Insertable(entity).ExecuteCommandAsync();
                        }
                        else
                        {
                            courseBase.CourseName = detail.ProductName;
                            courseBase.Amount = gjHeader.Price.Value;
                            courseBase.CourseNature = detail.CourseNature;
                            if (!string.IsNullOrWhiteSpace(detail.CourseNature))
                            {
                                courseBase.CourseNature = detail.CourseNature;
                            }
                            courseBase.ChargeTypeCode = detail.ChargeTypeName;
                            if (!string.IsNullOrWhiteSpace(detail.TrainObject))
                            {
                                courseBase.TrainingObjects = detail.TrainObject;
                            }
                            courseBase.BU = header.DemandSourceName;
                            courseBase.EstimatedNumberClasses = gjHeader.ClassCount.Value;
                            courseBase.ChargeDif = gjHeader.Unit;
                            courseBase.TrainDays = detail.Days;
                            courseBase.StandardTeacherCount = detail.StandardTeacherCount;
                            courseBase.StandardStudentCount = gjHeader.PeopleCount.Value;
                            courseBase.CreateUserId = businessProcess.StartUserId;
                            courseBase.CreateDate = businessProcess.FinishTime;
                            courseBase.Status = 1;

                            await _db.Updateable(courseBase).ExecuteCommandAsync();
                        }
                    }
                }

                return;
            }
            catch(Exception ex)
            {
                _logger.Error($"根据课程编号同步数据到CourseBase表，SyncDataToCourseBaseForMaterialCode：{ex.Message}");
            }
        }
    }
}